﻿using Audit.Core;
using Audit.MySql.Providers;
using Nest;

namespace AntDesignProCore.MVC
{
  public class ESCustomAuditDataProvider : AuditDataProvider
  {
    private readonly ElasticClient _elasticClient;

    public ESCustomAuditDataProvider(ElasticClient elasticClient)
    {
      _elasticClient = elasticClient;

      // 创建索引并设置映射
      var createIndexResponse = _elasticClient.Indices.Create("audit_log_write", c => c
          .Map<dynamic>(m => m
              .Properties(ps => ps
                  .Keyword(k => k.Name("id")) // id 字段，使用 `Keyword` 类型用于精确匹配
                  .Keyword(k => k.Name("audit_type")) // audit_type 字段
                  .Text(t => t.Name("audit_data")) // audit_data 字段，使用 `Text` 来存储 JSON 字符串
                  .Date(d => d.Name("timestamp")) // timestamp 字段，使用 `Date`
              )
          )
      );
    }

    // 重写 InsertEvent 方法来处理事件存储 _db.SaveChanges()
    public override object InsertEvent(AuditEvent auditEvent)
    {
      // 处理自定义逻辑，可以记录到日志、文件、数据库等
      HandleAuditEvent(auditEvent);

      // 转换为 Elasticsearch 所需的数据格式
      var auditEventForEs = new AuditEventForEs
      {
        Id = Guid.NewGuid().ToString(), // 或者从 auditEvent 获取对应的 id
        AuditType = auditEvent.EventType, // 使用 EventType 作为 audit_type
        AuditData = auditEvent.ToJson(), // 将 AuditEvent 转换为 JSON 字符串
        Timestamp = DateTime.Now // 使用 Event 的时间戳
      };
      Console.WriteLine($"InsertEvent:--------------------------------------------");
      // 将数据推送到 Elasticsearch
      var response = _elasticClient.IndexDocument(auditEventForEs);

      if (!response.IsValid)
      {
        // 处理插入失败的情况
        Console.WriteLine($"Error inserting event to Elasticsearch: {response.OriginalException.Message}");
      }

      // 返回插入结果
      return response.IsValid;

      //return true;
    }

    // 重写异步方法 _db.SaveChangesAsync()
    public override async Task<object> InsertEventAsync(AuditEvent auditEvent, CancellationToken cancellationToken = default)
    {
      // 处理自定义逻辑，可以记录到日志、文件、数据库等
      HandleAuditEvent(auditEvent);

      // 转换为 Elasticsearch 所需的数据格式
      var auditEventForEs = new AuditEventForEs
      {
        Id = Guid.NewGuid().ToString(), // 或者从 auditEvent 获取对应的 id
        AuditType = auditEvent.EventType, // 使用 EventType 作为 audit_type
        AuditData = auditEvent.ToJson(), // 将 AuditEvent 转换为 JSON 字符串
        Timestamp = DateTime.Now // 使用 Event 的时间戳
      };
      Console.WriteLine($"InsertEventAsync:--------------------------------------------");
      // 将数据推送到 Elasticsearch
      var response = await _elasticClient.IndexDocumentAsync(auditEventForEs, cancellationToken);

      if (!response.IsValid)
      {
        // 处理插入失败的情况
        Console.WriteLine($"Error inserting event to Elasticsearch: {response.OriginalException.Message}");
      }

      // 返回插入结果
      return response.IsValid;

      //return true;
    }

    private void HandleAuditEvent(AuditEvent auditEvent)
    {
      // 处理事件数据，这里可以记录到日志文件、发送到消息队列等
      Console.WriteLine($"EventData: {auditEvent.ToJson()}");
      Console.WriteLine($"EventType: {auditEvent.EventType}");
      Console.WriteLine($"Timestamp: {auditEvent.StartDate}");
      // 这里可以对审计事件进行进一步处理或修改
    }
  }

  public class AuditEventForEs
  {
    public string? Id { get; set; }
    public string? AuditType { get; set; }
    public string? AuditData { get; set; }
    public DateTime Timestamp { get; set; }
  }
}
